package com.york.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.york.model.dto.excel.CustomColumnWidthStyle;
import com.york.model.dto.excel.CustomSheetWriteHandler;
import com.york.model.dto.excel.DynamicHeader;
import com.york.model.dto.excel.ExcelSelected;
import com.york.model.dto.excel.ExcelSelectedResolve;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;

public class EasyExcelUtil {

	/**
     * 创建即将导出的sheet页（sheet页中含有带下拉框的列）
     * @param head 导出的表头信息和配置
     * @param sheetNo sheet索引
     * @param sheetName sheet名称
     * @param map 下拉选项信息
     * @return sheet页
     */
    public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer sheetNo, String sheetName, Map<String, String[]> selectedDataMap) {
        Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(head, selectedDataMap);

        return EasyExcel.writerSheet(sheetNo, sheetName)
                .head(head)
                .registerWriteHandler(new CustomColumnWidthStyle(null))	//自适应宽度
                .registerWriteHandler(new HorizontalCellStyleStrategy(getHeadWriteCellStyle(), getContentWriteCellStyle()))	//自适应宽度
                .registerWriteHandler(new CustomSheetWriteHandler(selectedMap)) //绑定下拉数据源
                .build();
    }

    public static <T> WriteSheet writeSelectedSheet(List<DynamicHeader> headers, Integer sheetNo, String sheetName) {
    	Map<Integer, ExcelSelectedResolve> selectedMap;
    	if(headers == null || headers.size() == 0) {
    		selectedMap = Collections.emptyMap();
    	}else {
    		selectedMap = resolveSelectedAnnotation(headers);
    	}

		return EasyExcel.writerSheet(sheetNo, sheetName).head(getHeader(headers))
				.registerWriteHandler(new CustomColumnWidthStyle(null)) // 自适应宽度
				.registerWriteHandler(new CustomSheetWriteHandler(selectedMap)) // 绑定下拉数据源
				.registerWriteHandler(new HorizontalCellStyleStrategy(getHeadWriteCellStyle(), getContentWriteCellStyle())) // 自适应宽度
				.build();
     }

    private static List<List<String>> getHeader(List<DynamicHeader> headers){
    	List<List<String>> list = new ArrayList<>();
    	for (DynamicHeader h : headers) {
    		list.add(Arrays.asList(h.getName()));
		}
    	return list;
    }

    public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer sheetNo, String sheetName) {
       return writeSelectedSheet(head, null, sheetNo, sheetName, null);
    }

	public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer[] headWidth, Integer sheetNo, String sheetName, Map<String, String[]> selectedDataMap) {
		if (selectedDataMap == null) {
			selectedDataMap = Collections.emptyMap();
		}
		Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(head, selectedDataMap);

		return EasyExcel.writerSheet(sheetNo, sheetName).head(head)
				.registerWriteHandler(new CustomColumnWidthStyle(headWidth)) // 自适应宽度
				.registerWriteHandler(new CustomSheetWriteHandler(selectedMap)) // 绑定下拉数据源
				.registerWriteHandler(new HorizontalCellStyleStrategy(getHeadWriteCellStyle(), getContentWriteCellStyle())) // 自适应宽度
				.build();
	}

    private static WriteCellStyle getHeadWriteCellStyle() {
    	//头策略使用默认 设置字体大小
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 12);
        headWriteCellStyle.setWriteFont(headWriteFont);
        return headWriteCellStyle;
    }

    private static WriteCellStyle getContentWriteCellStyle() {
    	//内容样式策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //垂直居中,水平居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

        //设置 自动换行
        contentWriteCellStyle.setWrapped(true);
        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 12);
        contentWriteCellStyle.setWriteFont(contentWriteFont);

        return contentWriteCellStyle;
    }

    /**
     * 解析表头类中的下拉注解
     * @param head 表头类
     * @param <T> 泛型
     * @return Map<下拉框列索引, 下拉框内容> map
     */
    private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(Class<T> head, Map<String,String[]> selectedDataMap) {
    	//用来存储对应的列与值对象
        Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>();

        // getDeclaredFields(): 返回全部声明的属性；getFields(): 返回public类型的属性
        Field[] fields = head.getDeclaredFields();
        for (int i = 0; i < fields.length; i++){
            Field field = fields[i];
            // 解析注解信息
            ExcelSelected selected = field.getAnnotation(ExcelSelected.class);
            ExcelProperty property = field.getAnnotation(ExcelProperty.class);
            if (selected != null) {
                ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();
                String[] source = excelSelectedResolve.resolveSelectedSource(selected, selectedDataMap.get(field.getName()));
                if (source != null && source.length > 0){
                    excelSelectedResolve.setSource(source);
                    excelSelectedResolve.setFirstRow(selected.firstRow());
                    excelSelectedResolve.setLastRow(selected.lastRow());
                    if (property != null && property.index() >= 0){
                        selectedMap.put(property.index(), excelSelectedResolve);
                    } else {
                        selectedMap.put(i, excelSelectedResolve);
                    }
                }
            }
        }

        return selectedMap;
    }

    /**
     * 解析表头类中的下拉注解
     * @param head 表头类
     * @return Map<下拉框列索引, 下拉框内容> map
     */
    private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(List<DynamicHeader> headers) {
    	//用来存储对应的列与值对象
        Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>();
        ExcelSelected selected = null;
		try {
			selected = headers.get(0).getClass().getDeclaredField("selectedSource").getAnnotation(ExcelSelected.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
        for (int i = 0; i < headers.size(); i++){
        	DynamicHeader header = headers.get(i);
            // 解析注解信息
            if (header.getSelectedSource() != null && header.getSelectedSource().length>0) {
                ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();
                String[] source = excelSelectedResolve.resolveSelectedSource(selected, header.getSelectedSource());
                if (source != null && source.length > 0){
                    excelSelectedResolve.setSource(source);
                    excelSelectedResolve.setFirstRow(selected.firstRow());
                    excelSelectedResolve.setLastRow(selected.lastRow());
                    selectedMap.put(i, excelSelectedResolve);
                }
            }
        }

        return selectedMap;
    }
}
